/*
 * Copyright 2020-2021 redragon.dongbin
 *
 * This file is part of redragon-erp/赤龙ERP.

 * redragon-erp/赤龙ERP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.

 * redragon-erp/赤龙ERP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with redragon-erp/赤龙ERP.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.erp.prod.bom.service.spring;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.redragon.commons.lang.Times;
import org.redragon.framework.hibernate.model.Pages;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.erp.common.inv.input.service.InvInputHeadService;
import com.erp.common.inv.stock.service.InvStockService;
import com.erp.masterdata.common.service.MasterDataCommonService;
import com.erp.masterdata.material.dao.model.MdMaterial;
import com.erp.prod.bom.dao.ProdBomHeadDao;
import com.erp.prod.bom.dao.model.ProdBomHead;
import com.erp.prod.bom.dao.model.ProdBomHeadCO;
import com.erp.prod.bom.dao.model.ProdBomLine;
import com.erp.prod.bom.dao.model.ProdBomLineCO;
import com.erp.prod.bom.service.ProdBomHeadService;
import com.erp.prod.bom.service.ProdBomLineService;

@Service
@Transactional(rollbackFor=Exception.class)
public class ProdBomHeadServiceImpl implements ProdBomHeadService {

    //注入Dao
    @Autowired
    private ProdBomHeadDao prodBomHeadDao;
    @Autowired
    private ProdBomLineService prodBomLineService;
    @Autowired
    @Qualifier("invStockServiceCommon")
    private InvStockService invStockServiceCommon;
    @Autowired
    @Qualifier("invInputHeadServiceCommon")
    private InvInputHeadService invInputHeadServiceCommon;
    @Autowired
    private MasterDataCommonService masterDataCommonService;
    
    @Override
    public void insertDataObject(ProdBomHead obj) {
        this.prodBomHeadDao.insertDataObject(obj);
    }

    @Override
    public void updateDataObject(ProdBomHead obj) {
        this.prodBomHeadDao.updateDataObject(obj);
    }
    
    @Override
    public void insertOrUpdateDataObject(ProdBomHead obj) {
        this.prodBomHeadDao.insertOrUpdateDataObject(obj);
    }

    @Override
    public void deleteDataObject(ProdBomHead obj) {
        this.prodBomHeadDao.deleteDataObject(obj);
    }

    @Override
    public List<ProdBomHead> getDataObjects() {
        return this.prodBomHeadDao.getDataObjects();
    }

    @Override
    public ProdBomHead getDataObject(int id) {
        return this.prodBomHeadDao.getDataObject(id);
    }

    @Override
    public ProdBomHead getDataObject(String code) {
        return this.prodBomHeadDao.getDataObject(code);
    }

    @Override
    public List<ProdBomHead> getDataObjects(ProdBomHeadCO paramObj) {
        return this.prodBomHeadDao.getDataObjects(paramObj);
    }

    @Override
    public List<ProdBomHead> getDataObjects(Pages pages) {
        return this.prodBomHeadDao.getDataObjects(pages);
    }
    
    @Override
    public List<ProdBomHead> getDataObjects(Pages pages, ProdBomHeadCO paramObj) {
        return this.prodBomHeadDao.getDataObjects(pages, paramObj);
    }
    
    @Override
    public List<Map<String, Object>> getDataObjectsArray(Pages pages, ProdBomHeadCO paramObj) {
        return this.prodBomHeadDao.getDataObjectsArray(pages, paramObj);
    }
    
    @Override
    public List<ProdBomHead> getDataObjectsForDataAuth(String dataAuthSQL, Pages pages, ProdBomHeadCO paramObj) {
        return this.prodBomHeadDao.getDataObjectsForDataAuth(dataAuthSQL, pages, paramObj);
    }
    
    @Override
    public ProdBomHead getProdBomHeadByMaterialCode(String materialCode) {
        return this.prodBomHeadDao.getProdBomHeadByMaterialCode(materialCode);
    }
    
    @Override
    public List<ProdBomLine> getBomMaterialList(List<ProdBomLine> list, String materialCode, BigDecimal baseQuantity, BigDecimal baseProducePreDays, Date planEndDate, String mpsLineCode) {
        //根据物料获取bom头
        ProdBomHead prodBomHead = this.prodBomHeadDao.getProdBomHeadByMaterialCode(materialCode);
        if(prodBomHead!=null) {
            //分页查询数据
            Pages pages = new Pages();
            pages.setPage(1);
            pages.setMax(100);
            ProdBomLineCO prodBomLineCO = new ProdBomLineCO();
            prodBomLineCO.setBomHeadCode(prodBomHead.getBomHeadCode());
            //获取bom行
            List<ProdBomLine> prodBomLineList = this.prodBomLineService.getBomLineListByBomHeadCode(pages, prodBomLineCO);
            
            if(prodBomLineList!=null&&prodBomLineList.size()>0) {
                //循环递归
                for(int a=0;a<prodBomLineList.size();a++) {
                    ProdBomLine prodBomLine = prodBomLineList.get(a);
                    //添加物料清单行
                    //递归计算数量
                    BigDecimal realQuantity = prodBomLine.getQuantity().multiply(baseQuantity);
                    //获取库存数量
                    BigDecimal stockQuantity = this.invStockServiceCommon.getMaterialStockNumber(prodBomLine.getMaterialCode());
                    //获取预计接收数量
                    BigDecimal willInputQuantity = this.invInputHeadServiceCommon.getInputQuantityForNotStock(prodBomLine.getMaterialCode());
                    //计算结果
                    BigDecimal countQuantity = realQuantity.subtract(stockQuantity).subtract(willInputQuantity);
                    //如果计算结果数量足够，则此物料跳过生成需求计划
                    if(countQuantity.doubleValue()<=0) {
                        continue;
                    }
                    prodBomLine.setCountQuantity(countQuantity);
                    //递归计算前置期
                    BigDecimal producePreDays = prodBomLine.getProducePreDays();
                    prodBomLine.setCountProducePreDays(producePreDays.add(baseProducePreDays));
                    //计算开工日期
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String endDate = df.format(planEndDate);
                    Times time = new Times();
                    time.changeDate(endDate, Calendar.DAY_OF_MONTH, -prodBomLine.getCountProducePreDays().intValue());
                    prodBomLine.setPlanStartDate(time.getJavaDate());
                    //计算完工日期
                    df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String startDate = df.format(prodBomLine.getPlanStartDate());
                    time = new Times();
                    time.changeDate(startDate, Calendar.DAY_OF_MONTH, producePreDays.intValue());
                    prodBomLine.setPlanEndDate(time.getJavaDate());
                    
                    list.add(prodBomLine);
                    
                    this.getBomMaterialList(list, prodBomLine.getMaterialCode(), prodBomLine.getCountQuantity(), prodBomLine.getCountProducePreDays(), planEndDate, mpsLineCode);
                }
            }
        }
        
        return list;
    }
    
    @Override
    public String validateBom(Map<String, String> materialMap, String materialCode, String parentMaterialCode, Map<String, String> validateResultMap) {
        String validateResult = null;
        //如果已经报错则直接return
        if(StringUtils.isNotBlank(validateResultMap.get("validateResult"))) {
            return validateResultMap.get("validateResult");
        }
        
        //根据物料获取bom头
        ProdBomHead prodBomHead = this.prodBomHeadDao.getProdBomHeadByMaterialCode(materialCode);
        if(prodBomHead!=null) {
            //获取物料信息
            MdMaterial mdMaterial = this.masterDataCommonService.getMdMaterialInfoCache(materialCode);
            
            //是否存在物料属性
            if(StringUtils.isBlank(mdMaterial.getBomProperty())) {
                validateResult = "["+materialCode+" "+mdMaterial.getMaterialName()+"]没有物料属性，请先维护物料主数据";
                validateResultMap.put("validateResult", validateResult);
                return validateResult;
            }
            
            //自制是否存在前置期
            if(mdMaterial.getBomProperty().equals("MAKE")) {
                Integer producePreDays = mdMaterial.getProducePreDays();
                if(producePreDays==null) {
                    validateResult = "["+materialCode+" "+mdMaterial.getMaterialName()+"]没有生产前置期，请先维护物料主数据";
                    validateResultMap.put("validateResult", validateResult);
                    return validateResult;
                }
            }
            
            //分页查询数据
            Pages pages = new Pages();
            pages.setPage(1);
            pages.setMax(100);
            ProdBomLineCO prodBomLineCO = new ProdBomLineCO();
            prodBomLineCO.setBomHeadCode(prodBomHead.getBomHeadCode());
            //获取bom行
            List<ProdBomLine> prodBomLineList = this.prodBomLineService.getBomLineListByBomHeadCode(pages, prodBomLineCO);
            
            if(prodBomLineList!=null&&prodBomLineList.size()>0) {
                //添加物料列表
                if(!materialMap.containsKey(materialCode)) {
                    String materialCodeTemp = "";
                    if(StringUtils.isNotBlank(parentMaterialCode)&&materialMap.containsKey(parentMaterialCode)) {
                        materialCodeTemp = materialMap.get(parentMaterialCode);
                    }
                    materialMap.put(materialCode, materialCodeTemp+":"+materialCode);
                }
                
                //循环
                for(int a=0;a<prodBomLineList.size();a++) {
                    ProdBomLine prodBomLine = prodBomLineList.get(a);
                    //获取物料信息
                    mdMaterial = this.masterDataCommonService.getMdMaterialInfoCache(prodBomLine.getMaterialCode());
                    
                    //是否存在物料属性
                    if(StringUtils.isBlank(mdMaterial.getBomProperty())) {
                        validateResult = "["+prodBomLine.getMaterialCode()+" "+mdMaterial.getMaterialName()+"]没有物料属性，请先维护物料主数据";
                        validateResultMap.put("validateResult", validateResult);
                        break;
                    }
                    
                    //自制是否存在前置期
                    if(mdMaterial.getBomProperty().equals("MAKE")) {
                        BigDecimal producePreDays = prodBomLine.getProducePreDays();
                        if(producePreDays==null) {
                            validateResult = "["+prodBomLine.getMaterialCode()+" "+mdMaterial.getMaterialName()+"]没有生产前置期，请先维护物料主数据";
                            validateResultMap.put("validateResult", validateResult);
                            break;
                        }
                    }
                    
                    //判断列表中是否存在当前物料
                    
                    if(materialMap.get(materialCode).contains(prodBomLine.getMaterialCode())) {
                        //获取物料信息
                        MdMaterial mdMaterialTemp = this.masterDataCommonService.getMdMaterialInfoCache(materialCode);
                        validateResult = "["+materialCode+" "+mdMaterialTemp.getMaterialName()+"]的物料清单形成了死循环，请核对后继续";
                        validateResultMap.put("validateResult", validateResult);
                        break;
                    }
                    
                    //递归
                    this.validateBom(materialMap, prodBomLine.getMaterialCode(), materialCode, validateResultMap);
                }
            }
        }
        
        return validateResultMap.get("validateResult");
    }
    
}